package org.manon.json;

import java.util.HashMap;
import java.util.Map;

import org.manon.json.analyse.ClassRegistry;
import org.manon.json.asm.ASMClassFactory;
import org.manon.json.asm.ASMGenerator;
import org.manon.json.io.Deserializer;
import org.manon.json.io.Serializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author <a href="mailto:jacques.militello@gmail.com">Jacques Militello</a>
 */
public final class JSONFactory implements SerializerProvider {

	/**
	 * Logger
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(JSONFactory.class);

	private final ASMClassFactory _holder = new ASMClassFactory();
	
	private ClassRegistry _registry = new ClassRegistry();
	
	private final Map<Class<?>, Serializer<?>> _serializers = new HashMap<Class<?>, Serializer<?>>();
	
	private final Map<Class<?>, Deserializer<?>> _deserializers = new HashMap<Class<?>, Deserializer<?>>();
	
	/**
	 *	Register a class to be serializable and deserializable 
	 */
	public void register(Class<?> toRegister) {
		_registry.register(toRegister);
	}
	
	public void init() {
		
		_registry.freeze();
		
		long start = System.currentTimeMillis();
		
		ASMGenerator.buildSerializers(_registry,_holder);
		ASMGenerator.buildDeSerializers(_registry,_holder);
		
		long stop = System.currentTimeMillis();
		
		LOGGER.info("create all Serializer and Deserializer in {} ms",(stop-start));
		
		for (Class<?> key :_registry.keySet()) {
			_serializers.put(key, _holder.newSerializerInstance(_registry.get(key),this));
			_deserializers.put(key, _holder.newDeserializerInstance(_registry.get(key)));
		}
		
		_registry = null;
	}
	
	public JSON newJSON() {
		return new JSONImpl(this);
	}
	
	/**
	 * @see org.manon.json.SerializerProvider#getSerialiser(java.lang.Class)
	 */
	@SuppressWarnings("unchecked")
	public <T> Serializer<T> getSerialiser(Class<T> entityClass) {
		return  (Serializer<T>) _serializers.get(entityClass);
	}

	
	@SuppressWarnings("unchecked")
	public <T> Deserializer<T> getDeserializer(Class<?> entityClass) {
		return (Deserializer<T>) _deserializers.get(entityClass);
	}

	
	
}